import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.logging.Logger;

public class Server {
    private Selector selector = null;

    private ServerSocketChannel serverSocketChannel = null;

    private InetSocketAddress serverAddress = null;

    private String BASE_DIRECT = "C:\\Users\\humble\\projectCenter\\NIO_demo\\src\\user_files";

    private Charset charset = StandardCharsets.UTF_8;

    private ByteBuffer buffer = null;

    private static final Logger logger = Logger.getLogger(Server.class.getName());

    public Server(int port) throws IOException {
        buffer = ByteBuffer.allocate(BufferConfig.BUFFER_SIZE);
        serverAddress = new InetSocketAddress(port);
    }

    public void startServer() throws IOException {
        selector = Selector.open();
        serverSocketChannel = ServerSocketChannel.open();
        // 设置为非阻塞
        serverSocketChannel.configureBlocking(false);
        // 绑定具体端口
        serverSocketChannel.socket().bind(serverAddress);
        // 注册到选择其中，并监听连接事件
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        while (true) {
            while (selector.select() > 0) {
                Iterator<SelectionKey> iterator = selector.keys().iterator();
                while (iterator.hasNext()) {
                    SelectionKey key = iterator.next();
                    if (key.isAcceptable()) {
                        SocketChannel socketChannel = serverSocketChannel.accept();

                        if (socketChannel == null) continue;
                        socketChannel.configureBlocking(false);
                        socketChannel.register(selector, SelectionKey.OP_READ);
                        key.cancel();

                    } else if (key.isReadable()) {
                        processData(key);
                        key.cancel();
                    }
                }
            }
        }
    }

    public void processData(SelectionKey key) throws IOException {
        SocketChannel socketChannel = (SocketChannel) key.channel();
        int readLength = 0;
        long fileLength = 0;
        int position = 0;
        // 创建文件管道
        FileChannel fileChannel = null;
        buffer.clear();
        while ((readLength = socketChannel.read(buffer)) > 0) {
            buffer.flip();
            if (fileLength == 0) {
                // 读取文件名：
                int nameLength = buffer.getInt();
                byte[] nameBytes = new byte[nameLength];
                buffer.get(nameBytes);
                String fileName = new String(nameBytes, charset);
                String fullName = BASE_DIRECT + File.separator + fileName;
                File file = new File(fullName);
                if(!file.exists()){
                    file.createNewFile();
                }

                // 注册文件管道
                fileChannel = new FileOutputStream(file).getChannel();

                //获取文件长度
                fileLength = buffer.getLong();
            }
            logger.info("文件传输开始");
            if (position < fileLength) {
                int writeLength = fileChannel.write(buffer);
                position += writeLength;
            }
            buffer.clear();
        }
        fileChannel.close();

    }

    public static void main(String[] args) throws IOException {
        Server server = new Server(12345);
        server.startServer();
    }
}
